﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Platform;
using System.Drawing;
using OpenTK.Graphics.OpenGL;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using System.Globalization;
using OpenTK.Input;


namespace NLE
{
    public class ImageControl: OpenTK.GLControl
    {
        #region Fields
        bool _loaded = false;

        public MainForm MainForm { get; set; }

        Stopwatch _stopWatch = new Stopwatch(); // available to all event handlers

        Texture2D _pixelTexture = null;

        Dictionary<String, LibraryImage> _textureLibrary = new Dictionary<string, LibraryImage>();

        public Dictionary<String, LibraryImage> TextureLibrary
        {
            get { return _textureLibrary; }
        }

        public bool EnableGrid { get; set; }

        public UndoHandler UndoHandler { get; set; }

        // Timer controls the rotation speed.
        Stopwatch _timer;

        // A grid line every 64 pixels
        public float GridSize { get; set; }

        float _mouseRelativeX;
        float _mouseRelativeY;

        float _mouseLastX;
        float _mouseLastY;

        bool _isHoldingShift = false;
        bool _isHoldingCtrl = false;

        bool _hasPressedKey = false;

        bool _hasStartedDraggingSelection = false;

        Point _startSelectionBox;

        private List<Layer> _layers = new List<Layer>();

        public List<Layer> Layers
        {
            get { return _layers; }
            set { _layers = value; }
        }

        public Layer ActiveLayer { get; set; }

        public Texture2D PreviewImage { get; set; }

        bool _pressed = false;



        LevelObject _lastUsedObject = null;
        LevelObject _lastHoveredObject = null;

        List<LevelObject> _selectedObjects = new List<LevelObject>();

        List<LevelObject> AllLevelObjects
        {
            get
            {
                List<LevelObject> tempList = new List<LevelObject>();
                foreach (Layer l in Layers)
                {
                    tempList.AddRange(l.LevelObjects);
                }
                return tempList;
            }
        }

        //public LevelObject SelectedObject { get { return _selectedObject; } }

        public Dictionary<string, string> _properties = new Dictionary<string, string>();

        public Dictionary<string, string> Properties { get { return _properties; } }

        public enum CurrentMode { PlacementMode, TranslationMode, RotationMode, ScaleMode, zOrderMode }

        public CurrentMode _currentMode = CurrentMode.PlacementMode;

        #endregion

        public ImageControl()
            : base()
        {
            Load += new EventHandler(ImageControl_Load);
            Paint += new PaintEventHandler(ImageControl_Paint);
            KeyDown += new KeyEventHandler(ImageControl_KeyDown);
            Resize += new EventHandler(ImageControl_Resize);
        }




        void ImageControl_Resize(object sender, EventArgs e)
        {
            if (!_loaded)
                return;

            SetupViewport();
            Invalidate();


        }

        void ImageControl_Paint(object sender, PaintEventArgs e)
        {

            if (!_loaded)
                return;

            Draw();

            SwapBuffers();
        }

        void ImageControl_Load(object sender, EventArgs e)
        {

            _loaded = true;



            SetupViewport();

            Initialize();
        }

        void GetUniqueName(LevelObject pLevelObject)
        {
            string name = pLevelObject.TextureName;

            bool isUniqueName = false;

            int count = 1;

            do
            {
                if (!isUniqueName)
                {
                    // Let's try something else
                    pLevelObject.Name = name + "_" + count;
                    count++;
                }  

                bool found = false;
                foreach (var layer in Layers)
                {
                    foreach (var levelobject in layer.LevelObjects)
                    {
                        if (levelobject.Name == pLevelObject.Name)
                        {
                            // Name already exists! We can't use it
                            // Let's generate a new name
                            found = true;
                        }
                    }
                }

                if (!found)
                {
                    isUniqueName = true;
                }


            } while (!isUniqueName);


        }



        void ImageControl_KeyDown(object sender, KeyEventArgs e)
        {
            _isHoldingShift = e.Shift;
            _isHoldingCtrl = e.Control;

            if (HasMouseInsideControl())
            {

                if (e.KeyCode == Keys.T)
                {
                    _currentMode = CurrentMode.TranslationMode;
                    MainForm.cmbMode.SelectedIndex = 1;

                }
                //else if (e.KeyCode == Keys.I)
                //{
                //    _currentMode = CurrentMode.PropertiesMode;
                //    MainForm.cmbMode.SelectedIndex = 2;
                //}
                else if (e.KeyCode == Keys.Z && _isHoldingCtrl && !_hasPressedKey)
                {
                    UndoHandler.DoUndo();
                    _hasPressedKey = true;
                }
                else if (e.KeyCode == Keys.Delete)
                {
                    foreach (LevelObject levelObject in _selectedObjects)
                    {
                        DeleteObject(levelObject);
                        MainForm.AddUndoItem(new Action() { Object = levelObject, Type = Action.ActionType.Deletion });
                    }
                    _selectedObjects.Clear();

                }
                else if (e.KeyCode == Keys.Y && _isHoldingCtrl && !_hasPressedKey)
                {
                    _hasPressedKey = true;
                    UndoHandler.DoRedo();
                }
                else if (e.KeyCode == Keys.Z && !_isHoldingCtrl)
                {
                    _currentMode = CurrentMode.zOrderMode;
                    MainForm.cmbMode.SelectedIndex = 4;
                }
                else if (e.KeyCode == Keys.R)
                {
                    _currentMode = CurrentMode.RotationMode;
                    MainForm.cmbMode.SelectedIndex = 2;
                }
                else if (e.KeyCode == Keys.P)
                {
                    _currentMode = CurrentMode.PlacementMode;
                    MainForm.cmbMode.SelectedIndex = 0;
                }
                else if (e.KeyCode == Keys.S)
                {
                    _currentMode = CurrentMode.ScaleMode;
                    MainForm.cmbMode.SelectedIndex = 3;
                }
                else if (e.KeyCode == Keys.F5)
                {
                    MainForm.btnTest_Click(null, null);
                }
                else if (e.KeyCode == Keys.Right)
                {
                    foreach (LevelObject levelObject in _selectedObjects)
                    {
                        levelObject.Position = levelObject.Position + new Vector2(1.0f, 0.0f);
                    }
                }
                else if (e.KeyCode == Keys.Up)
                {
                    foreach (LevelObject levelObject in _selectedObjects)
                    {
                        levelObject.Position = levelObject.Position + new Vector2(0.0f, 1.0f);
                    }
                }
                else if (e.KeyCode == Keys.Left)
                {
                    foreach (LevelObject levelObject in _selectedObjects)
                    {
                        levelObject.Position = levelObject.Position + new Vector2(-1.0f, 0.0f);
                    }
                }
                else if (e.KeyCode == Keys.Down)
                {
                    foreach (LevelObject levelObject in _selectedObjects)
                    {
                        levelObject.Position = levelObject.Position + new Vector2(0.0f, -1.0f);
                    }
                }

            }

        }

        protected override bool IsInputKey(Keys keyData)
        {
            if ( keyData == Keys.Left
                || keyData == Keys.Right
                || keyData == Keys.Down
                || keyData == Keys.Up)
            {
                return true;
            }

 	         return base.IsInputKey(keyData);
        }

        void ImageControl_KeyUp(object sender, KeyEventArgs e)
        {
            _hasPressedKey = false;
            _isHoldingShift = e.Shift;
            _isHoldingCtrl = e.Control;
        }



        void ImageControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {


            //if (e.Button == System.Windows.Forms.MouseButtons.Left && _selectedObjects.Count == 1)
            //{
            //    _selectedObjects.Clear();
            //}
            if (_lastHoveredObject != null )
            {
                if (!_isHoldingCtrl && _selectedObjects.Count == 1)
                {
                    _selectedObjects.Clear();
                }
                if ((from o in _selectedObjects where o == _lastHoveredObject select o).Count() == 0) _selectedObjects.Add(_lastHoveredObject);
            }
            


            Mouse.Button = e.Button;
        }

        void ImageControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Mouse.Button = MouseButtons.None;

            if (e.Button == System.Windows.Forms.MouseButtons.Left && _lastHoveredObject == null)
            {
                _selectedObjects.Clear();
            }

  
            if (_hasStartedDraggingSelection 
                //&& e.Button == System.Windows.Forms.MouseButtons.Left
                )
            {
                // Selection complete
                _hasStartedDraggingSelection = false;

                Point A = _startSelectionBox;

                Vector2 length = Vector2.Subtract(new Vector2(A.X, A.Y), new Vector2(_startSelectionBox.X, _startSelectionBox.Y));


                Point B = Functions.GetMouseToScreenCoords(this);
                B.X += (int)length.X;
                Point C = Functions.GetMouseToScreenCoords(this);
                C.X += (int)length.X;
                C.Y += (int)length.Y;
                Point D = Functions.GetMouseToScreenCoords(this);
                D.Y += (int)length.Y;

                if (D.X < A.X || D.Y > A.Y)
                {
                    Point temp = A;
                    A = D;
                    D = temp;
                }

                // Update our selection
                foreach (LevelObject levelObject in AllLevelObjects)
                {
                    //Rectangle objectRectangle = new Rectangle((int)levelObject.Position.X, (int)levelObject.Position.Y, TextureLibrary[levelObject.TextureName].Texture.w, TextureLibrary[levelObject.TextureName].Texture.h);
                    bool found = false;

                    // Check all corners of the levelobject if they are inside the selection box
                    if ((levelObject.Position.X - levelObject.Origin.X) > A.X &&
                        (levelObject.Position.Y + levelObject.Origin.Y) < A.Y &&
                        (levelObject.Position.X - levelObject.Origin.X) + TextureLibrary[levelObject.TextureName].Texture.w < D.X &&
                        (levelObject.Position.Y + levelObject.Origin.Y) - TextureLibrary[levelObject.TextureName].Texture.h > D.Y) found = true; 

                    if ( found ) _selectedObjects.Add(levelObject);
                    
                }

                if (_selectedObjects.Count >= 1) SetPropertiesForLevelObject(_selectedObjects[0]);
            }

            if (_selectedObjects.Count == 0)
            {
                SetPropertiesForLevel();
            }

        }



        public void DeleteObject(LevelObject pLevelObject)
        {
            pLevelObject.Layer.LevelObjects.Remove(pLevelObject);

            // Remove also from tree node
            foreach (TreeNode parent in MainForm.treeLayers.Nodes)
            {
                foreach (TreeNode node in parent.Nodes)
                {
                    if (node.Name == pLevelObject.Name)
                    {
                        node.Remove();
                    }
                } 
            }
        }

        void ImageControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {


            Mouse.X = e.X;
            Mouse.Y = e.Y;

        }

        private void SetupViewport()
        {
            Camera.Instance.Control = this;

            int[] viewPort = new int[4];

            GL.GetInteger(GetPName.Viewport, viewPort);

            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            //Matrix4 proj = Camera.Instance.Projection;
            //GL.LoadMatrix(ref proj);
            //GL.MatrixMode(MatrixMode.Modelview);
            //Matrix4 view = Camera.Instance.View;
            //GL.LoadMatrix(ref view);

            int w = Width;
            int h = Height;

            GL.Ortho(0, w, 0, h, -1, 1);
            GL.MatrixMode(MatrixMode.Modelview);

            GL.PushAttrib(AttribMask.DepthBufferBit);

            GL.Disable(EnableCap.DepthTest);
            GL.Enable(EnableCap.Texture2D);
            
            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            GL.Viewport(0, 0, w, h);
        }

        bool HasMouseInsideControl()
        {
            System.Drawing.Point local = (new System.Drawing.Point((int)_mouseLastX, (int)_mouseLastY));

            return local.X > 0 && local.Y > 0 && local.X < Width && local.Y < Height;
        }



        public Layer AddLayer(string pName)
        {
            int count = 2;
            string name = pName;
            // Check if the name is unique
            // While the name is found in the list
            while (Layers.Find(
                delegate(Layer l)
                {
                    return l.Name == pName;
                }
            ) != null)
            {
                // Try a new name
                pName = name + " " + count;
                count++;
            }


            Layer layer = new Layer { Name = pName };
            layer.IsHidden = false;
            Layers.Add(layer);



            // Update treeview
            MainForm.treeLayers.Nodes.Add(pName, pName);



            //MainForm.treeLayers.Nodes[0].Nodes.Add("Test");
            MainForm.treeLayers.Nodes[pName].Checked = true;

            return layer;
        }

        public void AddToLayer(Layer pLayer, LevelObject pLevelObject)
        {
            pLayer.LevelObjects.Add(pLevelObject);

            // Add text label
            MainForm.treeLayers.Nodes[pLayer.Name].Nodes.Add(pLevelObject.Name, pLevelObject.Name);
            MainForm.treeLayers.Nodes[pLayer.Name].Nodes[pLevelObject.Name].Checked = !pLevelObject.IsHidden;
        }



        protected void Initialize()
        {
            Layers = new List<Layer>();

            MainForm.ResetLayers();
            

            // Start the animation timer.
            _timer = Stopwatch.StartNew();

            GridSize = 32.0f;
            EnableGrid = true;


            _pixelTexture = new Texture2D();
            _pixelTexture.Load(global::NLE.Properties.Resources.PixelTexture);

            

            UndoHandler = new UndoHandler(this);

            Camera.Instance.Position = new Vector3(0, 0, 0);

            // Hook the idle event to constantly redraw our animation.
            Application.Idle += delegate { Invalidate(); };

            this.MouseWheel += new MouseEventHandler(ModelViewerControl_MouseWheel);
            this.MouseClick += new MouseEventHandler(ModelViewerControl_MouseClick);
            this.MouseMove += new MouseEventHandler(ImageControl_MouseMove);
            this.MouseDown += new MouseEventHandler(ImageControl_MouseDown);
            this.MouseUp += new MouseEventHandler(ImageControl_MouseUp);
            this.KeyDown +=new KeyEventHandler(ImageControl_KeyDown);
            this.KeyUp += new KeyEventHandler(ImageControl_KeyUp);
        }

        void ModelViewerControl_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {            
            Focus();
        }

        void ModelViewerControl_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
        {

            float amount = 0.1f;

            if (Camera.Instance.Zoom >= 4.0f) amount = 0.2f;

            if (Camera.Instance.Zoom <= 0.5f) amount = 0.05f;

            amount = (float)e.Delta > 0 ? amount : -amount;

            //Point point = Functions.ToScreenCoords(this, new Point(Width / 2, Height / 2));

            Camera.Instance.Zoom += amount;

            // Update combo box zoom
            foreach (var item in MainForm.cmbZoom.Items)
            {
                string a = item.ToString();
                string b = (Camera.Instance.Zoom * 100) + " %";

                if (a == b)
                {
                    MainForm.cmbZoom.SelectedItem = item;
                }
            }

            // Adjust camera properties so it translates according to our zoom
            //Camera.Instance.Position = new Vector3((float)point.X, (float)point.Y, 0);
   
        }

        public void UpdateProperties(string pCell)
        {
            //MainForm.dgProperties.SelectedObject = _dataGridUsedObject;



            if (_selectedObjects.Count == 0)
            {
                // level properties
                for (int i = 0; i < MainForm.dgProperties.Rows.Count; i++)
                {
                    var row = MainForm.dgProperties.Rows[i];

                    string c1 = row.Cells[0].Value == null ? String.Empty : row.Cells[0].Value.ToString();
                    string c2 = row.Cells[1].Value == null ? String.Empty : row.Cells[1].Value.ToString();

                    string newProperty = c2;
                    string oldProperty = _properties.ContainsKey(c1) ? _properties[c1] : String.Empty;



                    if (String.IsNullOrEmpty(newProperty))
                    {
                        // It's empty, so we probably no longer want it anymore
                        // but only if the previous state wasn't empty
                        if (!String.IsNullOrEmpty(oldProperty))
                        {
                            _properties.Remove(c1);
                        }

                    }
                    else
                    {
                        _properties[c1] = newProperty;
                        MainForm.AddUndoItem(new Action() { Object = null, Type = Action.ActionType.PropertyChange, Property = c1, OldPropertyValue = oldProperty, NewPropertyValue = newProperty });
                    }
                }
            }
            else
            {
                // Update all selected objects with these new values
                    

                    foreach (LevelObject currentObject in _selectedObjects)
                    {
                        for (int i = 0; i < MainForm.dgProperties.Rows.Count; i++)
                        {
                            var row = MainForm.dgProperties.Rows[i];

                            string c1 = row.Cells[0].Value == null ? String.Empty : row.Cells[0].Value.ToString();
                            string c2 = row.Cells[1].Value == null ? String.Empty : row.Cells[1].Value.ToString();

                            if (!c1.Equals(pCell)) continue;

                            if (c1.Equals("X Position"))
                            {
                                if (String.IsNullOrEmpty(c2)) continue;

                                


                                Vector2 newPos = new Vector2(float.Parse(c2, NumberFormatInfo.InvariantInfo), currentObject.Position.Y);
                                Vector2 oldPos = currentObject.Position;

                                if (newPos.X == oldPos.X && newPos.Y == oldPos.Y) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.Translation, OldPosition = currentObject.Position, NewPosition = newPos });

                                currentObject.Position = newPos;


                            }
                            else if (c1.Equals("Y Position"))
                            {
                                if (String.IsNullOrEmpty(c2)) continue;

                                Vector2 newPos = new Vector2(currentObject.Position.X, float.Parse(c2, NumberFormatInfo.InvariantInfo));
                                Vector2 oldPos = currentObject.Position;

                                if (newPos.X == oldPos.X && newPos.Y == oldPos.Y) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.Translation, OldPosition = currentObject.Position, NewPosition = newPos });

                                currentObject.Position = newPos;
                            }
                            else if (c1.Equals("X Origin"))
                            {
                                if (String.IsNullOrEmpty(c2)) continue;

                                Vector2 newOrig = new Vector2(float.Parse(c2, NumberFormatInfo.InvariantInfo), currentObject.Origin.Y);
                                Vector2 oldOrig = currentObject.Origin;

                                if (newOrig.X == oldOrig.X && newOrig.Y == oldOrig.Y) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.OriginChange, OldOrigin = currentObject.Origin, NewOrigin = newOrig });

                                currentObject.Origin = newOrig;

                            }
                            else if (c1.Equals("Y Origin"))
                            {
                                if (String.IsNullOrEmpty(c2)) continue;

                                Vector2 newOrig = new Vector2(currentObject.Origin.X, float.Parse(c2, NumberFormatInfo.InvariantInfo));
                                Vector2 oldOrig = currentObject.Origin;

                                if (newOrig.X == oldOrig.X && newOrig.Y == oldOrig.Y) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.OriginChange, OldOrigin = currentObject.Origin, NewPosition = newOrig });

                                currentObject.Origin = newOrig;
                            }
                            else if (c1.Equals("X Scale"))
                            {
                                if (String.IsNullOrEmpty(c2)) continue;

                                Vector2 newScale = new Vector2(currentObject.Scale.X, float.Parse(c2, NumberFormatInfo.InvariantInfo));
                                Vector2 oldScale = currentObject.Scale;

                                if (newScale == oldScale) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.Scale, OldScale = currentObject.Scale, NewScale = newScale });

                                currentObject.Scale = newScale;
                            }
                            else if (c1.Equals("Y Scale"))
                            {
                                if (String.IsNullOrEmpty(c2)) continue;

                                Vector2 newScale = new Vector2(float.Parse(c2, NumberFormatInfo.InvariantInfo), currentObject.Scale.Y);
                                Vector2 oldScale = currentObject.Scale;

                                if (newScale == oldScale) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.Scale, OldScale = currentObject.Scale, NewScale = newScale });

                                currentObject.Scale = newScale;
                            }
                            else if (c1.Equals("Rotation (Degrees)"))
                            {
                                if (String.IsNullOrEmpty(c2)) continue;

                                float newRotation = float.Parse(c2, NumberFormatInfo.InvariantInfo);
                                float oldRotation = currentObject.Rotation;

                                if (newRotation == oldRotation) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.Rotation, OldRotation = currentObject.Rotation, NewRotation = newRotation });

                                currentObject.Rotation = newRotation;
                            }
                            else if (c1.Equals("Draw Order"))
                            {
                                if (String.IsNullOrEmpty(c2)) continue;

                                float newzOrder = float.Parse(c2, NumberFormatInfo.InvariantInfo);
                                float oldzOrder = currentObject.zOrder;

                                if (newzOrder == oldzOrder) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.zOrder, OldzOrder = currentObject.zOrder, NewRotation = newzOrder });

                                currentObject.zOrder = newzOrder;
                            }
                            else if (c1.Equals("Class Name"))
                            {
                                string newClass = c2;
                                string oldClass = currentObject.Class;

                                if (newClass.Equals(oldClass)) continue;

                                MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.PropertyChange, Property = "Class", OldPropertyValue = oldClass, NewPropertyValue = newClass });
                                currentObject.Class = c2;

                                if (!MainForm.cmbClass.Items.Contains(newClass))
                                {
                                    MainForm.cmbClass.Items.Add(newClass);
                                }
                            }
                            else
                            {


                                string newProperty = c2;
                                string oldProperty = currentObject.Properties.ContainsKey(c1) ? currentObject.Properties[c1] : String.Empty;


                                if (String.IsNullOrEmpty(newProperty))
                                {
                                    // It's empty, so we probably no longer want it anymore
                                    // but only if the previous state wasn't empty
                                    if (!String.IsNullOrEmpty(oldProperty))
                                    {
                                        currentObject.Properties.Remove(c1);
                                    }

                                }
                                else
                                {
                                    currentObject.Properties[c1] = newProperty;
                                    MainForm.AddUndoItem(new Action() { Object = currentObject, Type = Action.ActionType.PropertyChange, Property = c1, OldPropertyValue = oldProperty, NewPropertyValue = newProperty });
                                }

                            }



                        }                        
                    }


            }
        }

        public void SetPropertiesForLevelObject(LevelObject pLevelObject)
        {
            //MainForm.dgProperties.SelectedObject = pLevelObject;
            MainForm.dgProperties.Rows.Clear();

            MainForm.dgProperties.Rows.Add(new string[] { "Class Name", pLevelObject.Class });
            //MainForm.dgProperties.Rows.Add(new string[] { "Image Name", pLevelObject.Name });
            MainForm.dgProperties.Rows.Add(new string[] { "X Position", pLevelObject.Position.X.ToString(NumberFormatInfo.InvariantInfo), });
            MainForm.dgProperties.Rows.Add(new string[] { "Y Position", pLevelObject.Position.Y.ToString(NumberFormatInfo.InvariantInfo), });
            MainForm.dgProperties.Rows.Add(new string[] { "X Origin", pLevelObject.Origin.X.ToString(NumberFormatInfo.InvariantInfo), });
            MainForm.dgProperties.Rows.Add(new string[] { "Y Origin", pLevelObject.Origin.Y.ToString(NumberFormatInfo.InvariantInfo), });
            MainForm.dgProperties.Rows.Add(new string[] { "Rotation (Degrees)", pLevelObject.Rotation.ToString(NumberFormatInfo.InvariantInfo), });
            MainForm.dgProperties.Rows.Add(new string[] { "X Scale", pLevelObject.Scale.X.ToString(NumberFormatInfo.InvariantInfo), });
            MainForm.dgProperties.Rows.Add(new string[] { "Y Scale", pLevelObject.Scale.Y.ToString(NumberFormatInfo.InvariantInfo), });
            MainForm.dgProperties.Rows.Add(new string[] { "Draw Order", pLevelObject.zOrder.ToString(NumberFormatInfo.InvariantInfo), });

            foreach (var kvp in pLevelObject.Properties)
            {
                MainForm.dgProperties.Rows.Add(new string[] { kvp.Key, kvp.Value, });
            }

            //_selectedObjects.Clear();

            


            
        }

        public void SetPropertiesForLevel()
        {
            // Nothing selected
            MainForm.dgProperties.Rows.Clear();

            foreach (var kvp in Properties)
            {
                MainForm.dgProperties.Rows.Add(new string[] { kvp.Key, kvp.Value, });
            }

            //_selectedObjects.Clear();
            //MainForm.dgProperties.SelectedObject = _level;
        }

        void Tick(float dTime)
        {

            _mouseRelativeX = _mouseLastX - Mouse.X;
            _mouseRelativeY = _mouseLastY - Mouse.Y;

            _mouseLastX = Mouse.X;
            _mouseLastY = Mouse.Y;


            Camera.Instance.Tick(dTime);

            //Camera.Instance.Zoom += MouseLastZ;

            if (UndoHandler.UndoList.Count == 0)
            {
                ((ToolStripButton)MainForm.toolStrip1.Items["tlUndo"]).Enabled = false;
            }
            else
            {
                ((ToolStripButton)MainForm.toolStrip1.Items["tlUndo"]).Enabled = true;
            }

            if (UndoHandler.RedoList.Count == 0)
            {
                ((ToolStripButton)MainForm.toolStrip1.Items["tlRedo"]).Enabled = false;
            }
            else
            {
                ((ToolStripButton)MainForm.toolStrip1.Items["tlRedo"]).Enabled = true;
            }

            if (_currentMode != CurrentMode.PlacementMode)
            {
                MainForm.cmbClass.Enabled = false;
                MainForm.lblClass.Enabled = false;
                MainForm.cmbzOrder.Enabled = false;
                MainForm.lblzOrder.Enabled = false;
            }
            else
            {
                MainForm.cmbClass.Enabled = true;
                MainForm.lblClass.Enabled = true;
                MainForm.cmbzOrder.Enabled = true;
                MainForm.lblzOrder.Enabled = true;
            }

            Point s = Functions.GetMouseToScreenCoords(this);

            switch (_currentMode)
            {
                case CurrentMode.PlacementMode:
                    Cursor = Cursors.Cross;
                    break;
                case CurrentMode.TranslationMode:
                    Cursor = Cursors.SizeAll;
                    //this.Cursor = Cursors.Hand;
                    break;
                case CurrentMode.RotationMode:
                    Cursor = Cursors.PanNE;
                    break;
                case CurrentMode.ScaleMode:
                    Cursor = Cursors.UpArrow;
                    break;
                case CurrentMode.zOrderMode:
                    Cursor = Cursors.PanSouth;
                    break;
                default:
                    //Todo: assert here?
                    break;
            }



            if (MainForm.treeImages.SelectedNode != null && MainForm.treeImages.SelectedNode.Text.Contains("(Group)")) PreviewImage = null;


            // Pan camera
            if (Mouse.Button == MouseButtons.Right)
            {
                Camera.Instance.Position = new Vector3((Camera.Instance.Position.X + _mouseRelativeX / Camera.Instance.Zoom), (Camera.Instance.Position.Y - _mouseRelativeY / Camera.Instance.Zoom), 0);
            }


            if (MainForm.tlStop.Enabled && MainForm.Game.HasExited) MainForm.tlStop.Enabled = false;



            if (Mouse.Button == MouseButtons.Left &&
                Form.ActiveForm == MainForm &&
                HasMouseInsideControl() &&
                !MainForm.cmbMode.DroppedDown &&
                !MainForm.cmbClass.DroppedDown &&
                !MainForm.cmbzOrder.DroppedDown &&
                !MainForm.cmbGridSize.DroppedDown &&
                !MainForm.tlStop.Enabled &&
                !_hasStartedDraggingSelection)
            {

                Vector2 Pos = new Vector2(s.X, s.Y);

                if (_currentMode == CurrentMode.PlacementMode &&
                    PreviewImage != null &&
                     MainForm.treeImages.SelectedNode != null &&
                    !_pressed)
                {

                    if (ActiveLayer == null)
                    {
                        MessageBox.Show("Please add a layer first.");
                    }
                    else
                    {


                        Vector2 offset = new Vector2((int)((float)PreviewImage.w / 2.0f), (int)((float)PreviewImage.h / 2.0f));

                        //offset.Y = -offset.Y;

                        //Vector2.Subtract(ref Pos, ref offset, out Pos);


                        if (EnableGrid)
                        {
                            Pos = Pos.SnapToGrid(GridSize);
                        }

                        float zOrder = float.Parse(MainForm.cmbzOrder.Text.Substring(0, 3), CultureInfo.InvariantCulture.NumberFormat);



                        LevelObject tempObject = new LevelObject()
                        {
                            TextureName = MainForm.treeImages.SelectedNode.Name,
                            Position = Pos,
                            Rotation = MathHelper.DegreesToRadians(0),
                            Scale = new Vector2(1.0f, 1.0f),
                            zOrder = zOrder,
                            Class = MainForm.cmbClass.Text,
                            Layer = ActiveLayer,
                            Origin = offset,
                        };

                        GetUniqueName(tempObject);

                        AddToLayer(ActiveLayer, tempObject);



                        _pressed = true;


                        // Add an undo action
                        MainForm.AddUndoItem(new Action() { Object = tempObject, Type = Action.ActionType.Creation });

                    }
                }

                // Parse mouse actions
                if (_lastUsedObject == null)
                {
                    // Make a temporary list of all layers' objects combined


                    //Vector2 vP = o.Position;
                    //Vector2 vO = o.Origin;

                    //vO.Y = -vO.Y;

                    ////v.Add(o.Origin);
                    //Vector2 vPositionMinusOffset;

                    //Vector2.Subtract(ref vP, ref vO, out vPositionMinusOffset);



                    //var query = (from o in tempList
                    //             let bImageW = (float)_textureLibrary[o.TextureName].Texture.w * 1 * o.Scale
                    //             let bImageH = (float)_textureLibrary[o.TextureName].Texture.h * 1 * o.Scale
                    //             let vPositionMinusOffset = new Vector2(o.Position.X - o.Origin.X, o.Position.Y + o.Origin.Y)
                    //             where Embeds(s.X, s.Y, (int)(vPositionMinusOffset.X), (int)(vPositionMinusOffset.Y) - (int)bImageH, (int)bImageW, (int)bImageH)
                    //             && _textureLibrary[o.TextureName].Texture.bitmap.GetPixel((int)((float)(s.X - (int)vPositionMinusOffset.X) / o.Scale), (int)((float)((int)vPositionMinusOffset.Y - s.Y) / o.Scale)).A != 0
                    //             && o.IsHidden == false
                    //             orderby o.zOrder ascending
                    //             select o).Take(1);


                    //if (query.Count() > 0)
                    if ( _lastHoveredObject != null )
                    {
                        //_lastUsedObject = query.ElementAt(0);
                        _lastUsedObject = _lastHoveredObject;

                        foreach (LevelObject levelObject in _selectedObjects)
                        {


                            switch (_currentMode)
                            {
                                case CurrentMode.TranslationMode:
                                    if (_isHoldingShift)
                                    {
                                        // Shift copy
                                        LevelObject tempObject = new LevelObject()
                                        {
                                            TextureName = levelObject.TextureName,
                                            Position = levelObject.Position,
                                            Rotation = levelObject.Rotation,
                                            Scale = levelObject.Scale,
                                            zOrder = levelObject.zOrder,
                                            Class = levelObject.Class,
                                            Layer = levelObject.Layer,
                                            Origin = levelObject.Origin,
                                        };

                                        GetUniqueName(tempObject);

                                        // Copy properties as well
                                        tempObject.Properties = new Dictionary<string, string>(levelObject.Properties);

                                        //ActiveLayer.LevelObjects.Add(tempObject);
                                        AddToLayer(ActiveLayer, tempObject);

                                        _isHoldingShift = true;

                                        //_lastUsedObject = tempObject;
                                    }
                                    else
                                    {
                                        levelObject.LastUsedPositionBeforeAction = levelObject.Position;
                                    }
                                    SetPropertiesForLevelObject(_lastUsedObject);
                                    break;
                                //case CurrentMode.PropertiesMode:

                                //    // Update the properties window with this object data
                                //    SetPropertiesForLevelObject(_lastUsedObject);

                                //    break;
                                case CurrentMode.RotationMode:
                                    levelObject.LastUsedRotationBeforeAction = levelObject.Rotation;
                                    SetPropertiesForLevelObject(_lastUsedObject);
                                    break;
                                case CurrentMode.ScaleMode:
                                    levelObject.LastUsedScaleBeforeAction = levelObject.Scale;
                                    SetPropertiesForLevelObject(_lastUsedObject);
                                    break;
                                case CurrentMode.zOrderMode:
                                    levelObject.LastUsedzOrderBeforeAction = levelObject.zOrder;
                                    SetPropertiesForLevelObject(_lastUsedObject);
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    else
                    {
                        if (!_hasStartedDraggingSelection)
                        {
                            // Draw a selection box, if nothing inside then SetPropertiesForLevel()


                            _startSelectionBox = Functions.GetMouseToScreenCoords(this);
                            _hasStartedDraggingSelection = true;
                            _selectedObjects.Clear();
                        }

                    }
                }

                if (_lastUsedObject != null)
                {
                    foreach (LevelObject levelObject in _selectedObjects)
                    {
                        switch (_currentMode)
                        {
                            case CurrentMode.TranslationMode:
                                levelObject.Position = new Vector2(levelObject.Position.X - _mouseRelativeX / Camera.Instance.Zoom, levelObject.Position.Y + _mouseRelativeY / Camera.Instance.Zoom);
                                break;
                            //case CurrentMode.PropertiesMode:
                            //    break;
                            case CurrentMode.RotationMode:
                                levelObject.Rotation += _mouseRelativeX * 1f;
                                levelObject.Rotation -= _mouseRelativeY * 1f;
                                break;
                            case CurrentMode.ScaleMode:
                                levelObject.Scale = new Vector2(levelObject.Scale.X - _mouseRelativeX * 0.01f, levelObject.Scale.Y - _mouseRelativeY * 0.01f);
                                break;
                            case CurrentMode.zOrderMode:
                                // 0.9 = FAR
                                // 0.1 = CLOSE
                                if (_mouseRelativeY != 0)
                                {
                                    levelObject.zOrder -= _mouseRelativeY > 0 ? 0.01f : -0.01f;
                                }

                                levelObject.zOrder = Math.Max(0.01f, levelObject.zOrder);
                                levelObject.zOrder = Math.Min(0.99f, levelObject.zOrder);

                                levelObject.zOrder = (float)Math.Round((double)levelObject.zOrder, 2);
                                break;
                            default:
                                break;
                        }
                    }

                    //if (_currentMode != CurrentMode.DeletionMode)
                    //{
                    //    SetPropertiesForLevelObject(_lastUsedObject);
                    //}
                }

                _pressed = true;

            }
            if (Mouse.Button == MouseButtons.None)
            {
                if (_lastUsedObject != null)
                {
                    foreach (LevelObject levelObject in _selectedObjects)
                    {


                        switch (_currentMode)
                        {
                            case CurrentMode.PlacementMode:
                                break;
                            case CurrentMode.TranslationMode:


                                if (EnableGrid && (levelObject.LastUsedPositionBeforeAction.X != levelObject.Position.X || levelObject.LastUsedPositionBeforeAction.Y != levelObject.Position.Y))
                                {
                                    levelObject.Position = levelObject.Position.SnapToGrid(GridSize);
                                }

                                if (_isHoldingShift)
                                {
                                    // Add an undo action
                                    MainForm.AddUndoItem(new Action() { Object = levelObject, Type = Action.ActionType.Creation });
                                }
                                else
                                {
                                    // Add an undo action
                                    MainForm.AddUndoItem(new Action() { Object = levelObject, Type = Action.ActionType.Translation, OldPosition = levelObject.LastUsedPositionBeforeAction, NewPosition = _lastUsedObject.Position });
                                }
                                _isHoldingShift = false;

                                SetPropertiesForLevelObject(_lastUsedObject);


                                break;
                            case CurrentMode.RotationMode:

                                if (_isHoldingCtrl)
                                {
                                    float r = (float)Math.Round(levelObject.Rotation / 45.0f);
                                    levelObject.Rotation = r * 45.0f;
                                }

                                MainForm.AddUndoItem(new Action() { Object = _lastUsedObject, Type = Action.ActionType.Rotation, OldRotation = levelObject.LastUsedRotationBeforeAction, NewRotation = _lastUsedObject.Rotation });
                                break;
                            case CurrentMode.ScaleMode:
                                MainForm.AddUndoItem(new Action() { Object = _lastUsedObject, Type = Action.ActionType.Scale, OldScale = levelObject.LastUsedScaleBeforeAction, NewScale = _lastUsedObject.Scale });
                                break;
                            case CurrentMode.zOrderMode:
                                MainForm.AddUndoItem(new Action() { Object = _lastUsedObject, Type = Action.ActionType.zOrder, OldzOrder = levelObject.LastUsedzOrderBeforeAction, NewzOrder = _lastUsedObject.zOrder });
                                break;
                            default:
                                break;
                        }
                    }

                    _lastUsedObject = null;
                }
                _pressed = false;
            }
        }

        public void Draw()
        {

            float dTime = _timer.ElapsedMilliseconds / 1000;

            Tick(dTime);

            // Start the animation timer.
            _timer = Stopwatch.StartNew();

    
            Color backColor = Color.White;

            GL.ClearColor(backColor);

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            Point mouse = Functions.GetMouseToScreenCoords(this);

            int sX = mouse.X;
            int sY = mouse.Y;


            LevelObject previousHoveredObject = _lastHoveredObject;
            _lastHoveredObject = null;







            #region Draw the grid

            float gridSize = GridSize;

            if (Camera.Instance.Zoom <= 0.5f)
            {
                gridSize *= 2;
            }


            if (EnableGrid)
            {

                // Pixeltexture is 4 pixels in width and height
                float screenWidth = (float)Width / Camera.Instance.Zoom;
                float screenHeight = (float)Height / Camera.Instance.Zoom;

                int horizontalLines = (int)(screenWidth / gridSize);
                int verticalLines = (int)(screenHeight / gridSize);

                float gridWidth = 0.30f;

                for (int i = -verticalLines; i < verticalLines; i++)
                {
                    float xScale = screenWidth / 2.0f;

                    Vector2 position = new Vector2(Camera.Instance.Position.X, Camera.Instance.Position.Y);
                    Vector2 remain = position.GetGridRemainder(gridSize);
                    position += new Vector2(0.0f, gridSize) * i;
                    position += new Vector2(-screenWidth, 0.0f);
                    position -= remain;

                    _pixelTexture.DrawAt(this, position, 0.0f, new Vector2(xScale, Math.Max(gridWidth / Camera.Instance.Zoom, gridWidth)), Vector2.Zero, Color.Gray);
                }

                for (int i = -horizontalLines; i < horizontalLines; i++)
                {
                    float yScale = screenHeight / 2.0f;

                    Vector2 position = new Vector2(Camera.Instance.Position.X, Camera.Instance.Position.Y);
                    Vector2 remain = position.GetGridRemainder(gridSize);
                    position += new Vector2(gridSize, 0.0f) * i;
                    position += new Vector2(0.0f, screenHeight);
                    position -= remain;

                    _pixelTexture.DrawAt(this, position, 0.0f, new Vector2(Math.Max(gridWidth / Camera.Instance.Zoom, gridWidth), yScale), Vector2.Zero, Color.Gray);
                }



                _pixelTexture.DrawAt(this, new Vector2(0.0f, 0.0f), 0.0f, new Vector2(5.0f / Camera.Instance.Zoom, 5.0f / Camera.Instance.Zoom), new Vector2(2.0f, 2.0f), Color.Black);
            }
            #endregion


 



                var query = from levelObject in AllLevelObjects
                            orderby levelObject.zOrder descending
                            select levelObject;

                foreach (var o in query)
                {
                    if (o.IsHidden) continue;


                    Vector2 vP = o.Position;
                    //Vector2 vO = o.Origin;

                    //vO.Y = -vO.Y;

                    //v.Add(o.Origin);
                    //Vector2 vPositionMinusOffset;

                    //Vector2.Subtract(ref vP, ref vO, out vPositionMinusOffset);



                    //vP = vPositionMinusOffset.WorldToLocal(this);

                    Color drawColor = Color.White;

                    float bImageW = (float)_textureLibrary[o.TextureName].Texture.w * o.Scale.X;
                    float bImageH = (float)_textureLibrary[o.TextureName].Texture.h * o.Scale.Y;

                    //(_textureLibrary[o.TextureName].Texture.bitmap.GetPixel((int)((float)(sX - (int)vPositionMinusOffset.X) / o.Scale), (int)((float)((int)vPositionMinusOffset.Y - sY) / o.Scale)).A != 0) &&
                    if (
                        o.HasMouseInside(this) && 
                        
                        _currentMode != CurrentMode.PlacementMode)
                    {
                        if (previousHoveredObject == o)
                        {
                            switch (_currentMode)
                            {
                                case CurrentMode.TranslationMode:
                                //case CurrentMode.PropertiesMode:
                                case CurrentMode.ScaleMode:
                                case CurrentMode.zOrderMode:
                                case CurrentMode.RotationMode:
                                    drawColor = Color.Blue;
                                    break;
                            }

                        }

                        _lastHoveredObject = o;
                    }





                    bImageW = (float)_textureLibrary[o.TextureName].Texture.w * o.Scale.X;
                    bImageH = (float)_textureLibrary[o.TextureName].Texture.h * o.Scale.Y;


                    //_textureLibrary[o.TextureName].Texture.SetBlending(255, 255, 255, 255);

                    //_textureLibrary[o.TextureName].Texture.rotation = o.Rotation;

                    
                    //_textureLibrary[o.TextureName].Texture.Draw((int)vP.X, (int)vP.Y, (int)bImageW, (int)bImageH);

                    _textureLibrary[o.TextureName].Texture.DrawAt(this, o.Position, o.Rotation, o.Scale, o.Origin, drawColor);



                }

                foreach (LevelObject o in AllLevelObjects)
                {


                    foreach (LevelObject currentObject in (from p in _selectedObjects where o == p select p))
                    {

                        GL.Color3(Color.Yellow);

                        // Draw a box

                        float lineThickness = 1.0f / Camera.Instance.Zoom;

                        

                        // Up 
                        Vector2 offset = currentObject.Origin;
                        Vector2 origin = Vector2.Zero;

                        offset.Y = -offset.Y;

                        Vector2 pos = currentObject.Position - offset;

                        _pixelTexture.DrawAt(this, pos, 0.0f, new Vector2((float)TextureLibrary[currentObject.TextureName].Texture.w / 4.0f, lineThickness), origin, Color.Yellow);

                        _pixelTexture.DrawAt(this, pos + new Vector2(0.0f, -(float)TextureLibrary[currentObject.TextureName].Texture.h + 4.0f * lineThickness), 0.0f, new Vector2((float)TextureLibrary[currentObject.TextureName].Texture.w / 4.0f, lineThickness), origin, Color.Yellow);

                        _pixelTexture.DrawAt(this, pos, 0.0f, new Vector2(lineThickness, (float)TextureLibrary[currentObject.TextureName].Texture.h / 4.0f), origin, Color.Yellow);

                        _pixelTexture.DrawAt(this, pos + new Vector2((float)TextureLibrary[currentObject.TextureName].Texture.w - 4.0f * lineThickness, 0.0f), 0.0f, new Vector2(lineThickness, (float)TextureLibrary[currentObject.TextureName].Texture.h / 4.0f), origin, Color.Yellow);

                    }
                }
            //_pixelTexture.DrawAt(this, new Vector2(0.0f, 0.0f), 0.0f, new Vector2(100.0f, 100.0f), Color.White);

            float w = Width;
            float h = Height;



            // Draw our preview texture
            if (PreviewImage != null &&
                _currentMode == CurrentMode.PlacementMode)
            {

                Point P = Functions.GetMouseToScreenCoords(this);

                Vector2 Pos = new Vector2((int)P.X, (int)P.Y);

                if (EnableGrid)
                {
                    Pos = Pos.SnapToGrid(GridSize);
                }

                PreviewImage.SetBlending(255, 255, 255, 255);

                float zOrder = float.Parse(MainForm.cmbzOrder.Text.Substring(0, 3), CultureInfo.InvariantCulture.NumberFormat);

                Vector2 offset = new Vector2((int)((float)PreviewImage.w / 2.0f), (int)((float)PreviewImage.h / 2.0f));




               
                //PreviewImage.Draw((int)Pos.X, (int)Pos.Y, (int)((float)PreviewImage.w), (int)((float)PreviewImage.h));
                PreviewImage.DrawAt(this, Pos, 0.0f, new Vector2(1.0f, 1.0f), offset, Color.White);

                
            }



            // Draw selection box
            if (_startSelectionBox != null && _hasStartedDraggingSelection)
            {

                Point endPoint = Functions.GetMouseToScreenCoords(this);

                Vector2 beginPosition = new Vector2(_startSelectionBox.X, _startSelectionBox.Y);
                Vector2 endPosition = new Vector2(endPoint.X, endPoint.Y);

                Vector2 length = Vector2.Subtract(endPosition, beginPosition);

                Vector2 origin = Vector2.Zero;
                _pixelTexture.DrawAt(this, beginPosition, 0.0f, new Vector2(length.X / 4.0f, 1.0f), origin, Color.Blue);

                _pixelTexture.DrawAt(this, beginPosition + new Vector2(0.0f, length.Y), 0.0f, new Vector2(length.X / 4.0f, 1.0f), origin, Color.Blue);

                _pixelTexture.DrawAt(this, beginPosition, 0.0f, new Vector2(1.0f, -length.Y / 4.0f), origin, Color.Blue);

                _pixelTexture.DrawAt(this, beginPosition + new Vector2(length.X, 0.0f), 0.0f, new Vector2(1.0f, -length.Y / 4.0f), origin, Color.Blue);

                //_pixelTexture.DrawAt(this, position + new Vector2(0.0f, -(float)TextureLibrary[currentObject.TextureName].Texture.h + 4.0f), 0.0f, new Vector2((float)TextureLibrary[currentObject.TextureName].Texture.w / 4.0f, 1.0f), origin, Color.Yellow);

                //_pixelTexture.DrawAt(this, position, 0.0f, new Vector2(1.0f, (float)TextureLibrary[currentObject.TextureName].Texture.h / 4.0f), origin, Color.Yellow);

                //_pixelTexture.DrawAt(this, position + new Vector2((float)TextureLibrary[currentObject.TextureName].Texture.w - 4.0f, 0.0f), 0.0f, new Vector2(1.0f, (float)TextureLibrary[currentObject.TextureName].Texture.h / 4.0f), origin, Color.Yellow);



            }



            Point s = Functions.GetMouseToScreenCoords(this);



            if ( _lastHoveredObject != null)
            {
                //MainForm.statusBar.Text = "Object Position: (" + _lastUsedObject.Position.X + "," + _lastUsedObject.Position.Y + ")";
                //MainForm.statusBar.Text += ", Object Rotation: (" + _lastUsedObject.Rotation + "°)";
                //MainForm.statusBar.Text += ", Object Scale: (" + _lastUsedObject.Scale + ")";
                //MainForm.statusBar.Text += ", Object Draw Order: (" + _lastUsedObject.zOrder + ")";
                MainForm.toolStripStatusLabel1.Text = _lastHoveredObject.Name;
            }
            else
            {
                MainForm.toolStripStatusLabel1.Text = "";
                //MainForm.statusBar.Text = "Mouse Position: (" + s.X + "," + s.Y + "), Camera Zoom: (x" + Camera.Instance.Zoom + "), Camera Position: (" + Camera.Instance.Position.X + "," + Camera.Instance.Position.Y + ")";
            }
            MainForm.toolStripStatusLabel2.Text = "X: " + s.X;
            MainForm.toolStripStatusLabel3.Text = "Y: " + s.Y;



        }

    }




    public static class MyExtensions
    {
        public static Vector2 WorldToLocal(this Vector2 pPosition, Control pControl)
        {

            //pPosition = Vector2.Multiply(pPosition, Camera.Instance.Zoom);

            int w = (int)((float)pControl.Width / 2.0f);
            int h = (int)((float)pControl.Height / 2.0f);

            return new Vector2(pPosition.X + w - Camera.Instance.Position.X, pPosition.Y + h - Camera.Instance.Position.Y);
        }
        public static Vector2 LocalToWorld(this Vector2 pPosition, Control pControl)
        {

            //pPosition = Vector2.Divide(pPosition, Camera.Instance.Zoom);

            int w = (int)((float)pControl.Width / 2.0f);
            int h = (int)((float)pControl.Height / 2.0f);

            return new Vector2(pPosition.X - w + Camera.Instance.Position.X, pPosition.Y - h + Camera.Instance.Position.Y);
        }
        public static Vector2 SnapToGrid(this Vector2 pPosition, float pGridSize)
        {
            return new Vector2(
                (float)Math.Round((double)pPosition.X / (double)pGridSize) * pGridSize,
                (float)Math.Round((double)pPosition.Y / (double)pGridSize) * pGridSize
                );
        }
        public static Vector2 GetGridRemainder(this Vector2 v, float GridSize)
        {
            return v - v.SnapToGrid(GridSize);
        }
    }

    public static class Mouse
    {
        public static MouseButtons Button { get; set; }

        public static int X { get; set; }
        public static int Y { get; set; }


    }
}

